ifdef $(GENDEV)
ROOTDIR = $(GENDEV)
else
ROOTDIR = /opt/toolchains/sega
endif

MARSDEV  = $(WINHOME)/mars
TOOLSBIN = $(MARSDEV)/bin

LDSCRIPTSDIR = $(ROOTDIR)/ldscripts

LIBPATH = -L$(ROOTDIR)/sh-elf/lib -L$(ROOTDIR)/sh-elf/lib/gcc/sh-elf/4.6.2 -L$(ROOTDIR)/sh-elf/sh-elf/lib
INCPATH = -I. -I$(ROOTDIR)/sh-elf/include -I$(ROOTDIR)/sh-elf/sh-elf/include -I$(BASE_OUTPUT_DIR) \
         -I../../game -I../../game/rooms

CCFLAGS = -c -std=c11 -g -m2 -mb
CCFLAGS += -Wall -Wextra -pedantic -Wno-unused-parameter -Wimplicit-fallthrough=0 -Wno-missing-field-initializers -Wnonnull
CCFLAGS += -D__32X__ -DMARS
LDFLAGS = -T $(LDSCRIPTSDIR)/mars.ld -Wl,-Map=$(OUTPUT_DIR)/32x_output.map -nostdlib -Wl,--gc-sections --specs=nosys.specs
ASFLAGS = --big --defsym LINEAR_CROSSFADE=1

MARSHWCFLAGS := $(CCFLAGS)
MARSHWCFLAGS += -fno-lto

release: CCFLAGS += -Os -fomit-frame-pointer -ffast-math -funroll-loops -fno-align-loops -fno-align-jumps -fno-align-labels
release: CCFLAGS += -ffunction-sections -fdata-sections -flto
release: MARSHWCFLAGS += -O1
release: LDFLAGS += -flto

debug: CCFLAGS += -Os -ggdb -fno-omit-frame-pointer
debug: MARSHWCFLAGS += -O1 -ggdb -fno-omit-frame-pointer

PREFIX = $(ROOTDIR)/sh-elf/bin/sh-elf-
CC = $(PREFIX)gcc
AS = $(PREFIX)as
LD = $(PREFIX)ld
OBJC = $(PREFIX)objcopy
NM = $(PREFIX)nm

DD = dd
RM = rm -f

TARGET ?= Downland
LIBS = $(LIBPATH) -lc -lgcc -lgcc-Os-4-200 -lnosys

BUILD_DIR = build
SOURCE_DIR = source/32x

BASE_OUTPUT_DIR = out
OUTPUT_DIR = $(BASE_OUTPUT_DIR)/32x
SOURCE_OUTPUT_DIR = $(OUTPUT_DIR)/$(SOURCE_DIR)
OUTPUT_DIR_MD = $(BASE_OUTPUT_DIR)/md

# Sources
SS_SOURCE = $(wildcard $(SOURCE_DIR)/*.s)
CS = $(wildcard $(SOURCE_DIR)/*.c)

# External game sources
GAME_CS = $(wildcard ../../game/*.c)
ROOMS_CS = $(wildcard ../../game/rooms/*.c)

GAME_OUTPUT_DIR = $(OUTPUT_DIR)/game
ROOMS_OUTPUT_DIR = $(OUTPUT_DIR)/game/rooms

GAME_OBJS = $(patsubst ../../game/%.c, $(GAME_OUTPUT_DIR)/%.o, $(GAME_CS))
ROOMS_OBJS = $(patsubst ../../game/rooms/%.c, $(ROOMS_OUTPUT_DIR)/%.o, $(ROOMS_CS))

OBJ_SOURCE = $(SS_SOURCE:.s=.o) $(CS:.c=.o)
DOWNLAND_O = $(BASE_OUTPUT_DIR)/downland.o

OBJS = $(addprefix $(OUTPUT_DIR)/, $(OBJ_SOURCE)) $(DOWNLAND_O) $(GAME_OBJS) $(ROOMS_OBJS)

# ROM input
ROM_INPUT = gamedata/downland.rom

.PHONY: directories

release: always_build_md directories $(DOWNLAND_O) $(BASE_OUTPUT_DIR)/$(TARGET).32x

debug: always_build_md directories $(DOWNLAND_O) $(BASE_OUTPUT_DIR)/$(TARGET).32x

all: release

directories: $(SOURCE_OUTPUT_DIR) $(GAME_OUTPUT_DIR) $(ROOMS_OUTPUT_DIR)

$(SOURCE_OUTPUT_DIR):
	mkdir -p $@

$(GAME_OUTPUT_DIR):
	mkdir -p $@

$(ROOMS_OUTPUT_DIR):
	mkdir -p $@

$(OUTPUT_DIR_MD)/m68k.bin: 
	make -f $(BUILD_DIR)/Makefile_MD

always_build_md:
	make -f $(BUILD_DIR)/Makefile_MD

$(BASE_OUTPUT_DIR)/$(TARGET).32x: $(OUTPUT_DIR)/$(TARGET).elf
	$(OBJC) -O binary $< $(OUTPUT_DIR)/temp2.bin
	$(DD) if=$(OUTPUT_DIR)/temp2.bin of=$(OUTPUT_DIR)/temp.bin bs=192K conv=sync
	$(DD) if=$(OUTPUT_DIR)/temp.bin of=$@ bs=512K conv=sync

$(OUTPUT_DIR)/$(TARGET).elf: $(OBJS)
	$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@

$(SOURCE_OUTPUT_DIR)/_crt0.o: $(SOURCE_DIR)/_crt0.s $(OUTPUT_DIR_MD)/m68k.bin

$(SOURCE_OUTPUT_DIR)/marshw.o: $(SOURCE_DIR)/marshw.c
	$(CC) $(MARSHWCFLAGS) $(INCPATH) $< -o $@

$(SOURCE_OUTPUT_DIR)/%.o: $(SOURCE_DIR)/%.c
	$(CC) $(CCFLAGS) $(INCPATH) $< -o $@

$(SOURCE_OUTPUT_DIR)/%.o: $(SOURCE_DIR)/%.s
	$(AS) $(ASFLAGS) $(INCPATH) $< -o $@

$(GAME_OUTPUT_DIR)/%.o: ../../game/%.c | $(GAME_OUTPUT_DIR)
	$(CC) $(CCFLAGS) $(INCPATH) $< -o $@

$(ROOMS_OUTPUT_DIR)/%.o: ../../game/rooms/%.c | $(ROOMS_OUTPUT_DIR)
	$(CC) $(CCFLAGS) $(INCPATH) $< -o $@

# Assemble generated .s files from out/
$(BASE_OUTPUT_DIR)/%.o: $(BASE_OUTPUT_DIR)/%.s
	$(AS) $(ASFLAGS) $(INCPATH) $< -o $@

# Convert downland.rom to object file
$(DOWNLAND_O): $(ROM_INPUT)
	$(OBJC) -I binary -O elf32-sh -B sh $< $@

clean:
	make clean -f $(BUILD_DIR)/Makefile_MD
	$(RM) $(SOURCE_OUTPUT_DIR)/*.o $(GAME_OUTPUT_DIR)/*.o $(ROOMS_OUTPUT_DIR)/*.o $(OUTPUT_DIR_MD)/m68k.bin $(BASE_OUTPUT_DIR)/$(TARGET).32x \
	$(OUTPUT_DIR)/$(TARGET).elf $(OUTPUT_DIR)/32x_output.map $(OUTPUT_DIR)/temp.bin $(OUTPUT_DIR)/temp2.bin \
	$(DOWNLAND_O)
